package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.crm.help.SearchCustomerHelp;
import com.xbongbong.paas.business.rule.FormDataActiveRuleHelp;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.FormDataValidateDataHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.pojo.ExcelImportExtraPoJo;
import com.xbongbong.paas.pojo.dto.ActiveRuleDTO;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.vo.FormDataAddVO;
import com.xbongbong.paas.service.ExcelImportService;
import com.xbongbong.paas.service.ProModelService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.GaodeGeoHelper;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.TemplateErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.service.toolbox.elasticsearch.help.ProEsHelper;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.user.pojo.ReturnUserAndDepartmentPojo;
import com.xbongbong.pro.userteam.pojo.dto.VerifyUserTeamForImportDTO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.ext.CustomerEntityExt;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.PaasFormDataModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.service.ContactService;
import com.xbongbong.saas.service.CustomerService;
import com.xbongbong.saas.service.ScoreCalculateService;
import com.xbongbong.saas.service.UserTeamService;
import org.elasticsearch.action.support.WriteRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Excel导入
 *
 * @author lee
 * @date 2019/9/18 10:13
 */
@Service("excelImportService")
public class ExcelImportServiceImpl implements ExcelImportService {

    private static final Logger LOG = LoggerFactory.getLogger(ExcelImportServiceImpl.class);


    @Resource
    private FormDataValidateDataHelp formDataValidateDataHelp;
    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private PaasFormDataModel paasFormDataModel;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private CustomerService customerService;
    @Resource
    private ProEsHelper proEsHelper;
    @Resource
    private ContactService contactService;
    @Resource
    private SearchCustomerHelp searchCustomerHelp;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private FormDataActiveRuleHelp formDataActiveRuleHelp;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private ScoreCalculateService scoreCalculateService;
    @Resource
    private ProModelService proModelService;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;
    @Resource
    private IndexTypeModel indexTypeModel;

    @Override
    public FormDataAddVO addImportData(FormDataAddDTO formDataAddDTO, ExcelImportExtraPoJo excelImportExtraPoJo) throws XbbException {
        FormDataAddVO addVO = new FormDataAddVO();
        Integer saasMark = formDataAddDTO.getSaasMark();
        List<ReturnUserAndDepartmentPojo> ownerIdList = formDataAddDTO.getOwnerId();
        JSONObject dataList = formDataAddDTO.getDataList();
        Map<String, FieldAttrEntity> explainMap = formDataAddDTO.getExplainMap();
        Map<String, FieldAttrEntity> simpleExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (Objects.equals(formDataAddDTO.getIsImport(), BasicConstant.ONE) && CollectionsUtil.isNotEmpty(formDataAddDTO.getAttrList())) {
            for (String s : formDataAddDTO.getAttrList()) {
                FieldAttrEntity fieldAttrEntity = explainMap.get(s);
                if (Objects.nonNull(fieldAttrEntity)) {
                    simpleExplainMap.put(s, fieldAttrEntity);
                }
            }
        }
        try {
            ValidateDataDTO validateDataDTO = new ValidateDataDTO();
            BeanUtil.copyProperties(formDataAddDTO, validateDataDTO);
            validateDataDTO.setData(dataList);
            validateDataDTO.setExplainMap(explainMap);
            validateDataDTO.setOwnerIds(ownerIdList);
            if (!simpleExplainMap.isEmpty()) {
                validateDataDTO.setExplainMap(simpleExplainMap);
            }
            // 通用数据格式转换
            ProSaveHelp.analyticalData(validateDataDTO);
            formDataAddDTO.setCoUserId(validateDataDTO.getCoUserId());
            // 通用数据校验
            formDataValidateDataHelp.validateData(validateDataDTO);

            if (Objects.equals(saasMark, SaasMarkEnum.SAAS.getCode())) {
                // 保存前的数据校验和格式转换
                saasSaveHelp.beforeSave(validateDataDTO);
                // 校验完，将全部解释的字段map重新塞值
                validateDataDTO.setExplainMap(explainMap);
                VerifyUserTeamForImportDTO verifyUserTeamForImportDTO = new VerifyUserTeamForImportDTO();
                BeanUtil.copyProperties(formDataAddDTO, verifyUserTeamForImportDTO);
                if (Objects.equals(formDataAddDTO.getBusinessType(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
                    verifyUserTeamForImportDTO.setCreatorId(dataList.getString(CustomerManagementEnum.CREATOR.getAttr()));
                } else {
                    verifyUserTeamForImportDTO.setCreatorId(formDataAddDTO.getUserId());
                }
//                userTeamService.verifyMyTeamForImport(verifyUserTeamForImportDTO);
            } else if (Objects.equals(saasMark, SaasMarkEnum.PAAS.getCode())){
                //没有负责团队的 单负责人
                userTeamService.beforeVerifyUserTeam(validateDataDTO);
                // 校验完，将全部解释的字段map重新塞值
                validateDataDTO.setExplainMap(explainMap);
            }
            formDataAddDTO.setSaasNeedRedundantAttrPoJo(validateDataDTO.getSaasNeedRedundantAttrPoJo());
            PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
            BeanUtil.copyProperties(formDataAddDTO, paasFormDataEntity);
            // 所属部门的id，由前端传入 所属部门不可见，前端拿不到时，卡特建议直接赋值-1
            Long departmentId = Objects.isNull(validateDataDTO.getDepartmentId()) ? -1L : validateDataDTO.getDepartmentId();
            paasFormDataEntity.setDepartmentId(departmentId);
            formDataAddDTO.setDepartmentId(departmentId);
            if (Objects.nonNull(ownerIdList) && !ownerIdList.isEmpty()) {
                paasFormDataEntity.setOwnerId(Objects.toString(ownerIdList.get(0).getId(), ""));
            } else {
                String ownerId = formDataAddDTO.getUserId();
                paasFormDataEntity.setOwnerId(ownerId);
            }
            paasFormDataEntity.setData(dataList);
            // 客户导入流水号开启严控需要由系统生成
            String serialNo = formDataAddDTO.getSerialNo();
            FieldAttrEntity fieldAttrEntity = explainMap.get(FieldTypeEnum.SERIALNO.getAlias());
            if (!simpleExplainMap.isEmpty()) {
                fieldAttrEntity = simpleExplainMap.get(FieldTypeEnum.SERIALNO.getAlias());
            }
            if (Objects.nonNull(fieldAttrEntity) && Objects.equals(fieldAttrEntity.getStrictController(), BasicConstant.ONE)) {
                serialNo = saasSaveHelp.getSerialNo(formDataAddDTO.getSerialNo(), formDataAddDTO, formDataAddDTO.getCorpid(), explainMap.get(FieldTypeEnum.SERIALNO.getAlias()));
            }
            paasFormDataEntity.setSerialNo(serialNo);
            paasFormDataEntity.setMenuId(formDataAddDTO.getMenuId());
            paasFormDataEntity.setFlowStatus(FlowStatusEnum.NOT_NEED_APPROVAL.getType());
            paasFormDataEntity.setCreatorId(formDataAddDTO.getUserId());
            insert(formDataAddDTO, paasFormDataEntity, excelImportExtraPoJo);
            addVO.setDataId(paasFormDataEntity.getDataId());
            return addVO;
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("导入数据出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    private void insert(FormDataAddDTO formDataAddDTO, PaasFormDataEntity paasFormDataEntity, ExcelImportExtraPoJo excelImportExtraPoJo) throws XbbException {
        Long dataId = 0L;
        String corpid = formDataAddDTO.getCorpid();
        Integer saasMark = formDataAddDTO.getSaasMark();
        Integer businessType = formDataAddDTO.getBusinessType();
        JSONObject data = paasFormDataEntity.getData();
        //兼容审批移除上一步data放入的 ownerId, coUserId
        paasFormDataEntity.getData().remove(FieldTypeEnum.OWNERID.getAlias());
        paasFormDataEntity.getData().remove(FieldTypeEnum.COUSERID.getAlias());
        paasFormDataEntity.getData().remove(FieldTypeEnum.SERIALNO.getAlias());
        try {
            if (SaasMarkEnum.PAAS.getCode().equals(saasMark)) {
                paasFormDataModel.insert(paasFormDataEntity);
                dataId = paasFormDataEntity.getId();
                // 执行业务规则
                executionBusinessRule(formDataAddDTO, paasFormDataEntity);
            } else {
                if (businessType == null || businessType == 0) {
                    LOG.error("businessType为空");
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
                BeanUtil.copyProperties(formDataAddDTO, saasFormSaveDTO);
                XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
                SaasNeedRedundantAttrPojo saasNeedRedundantAttrPoJo;
                switch (xbbRefTypeEnum) {
                    case CUSTOMER_MANAGEMENT:
                        data.remove(CustomerManagementEnum.ADD_CONTACT.getAttr());
                        paasFormDataEntity.setData(data);
                        CustomerEntityExt customerEntityExt = new CustomerEntityExt();
                        BeanUtil.copyProperties(paasFormDataEntity, customerEntityExt);
                        customerModel.insert(customerEntityExt);
                        dataId = customerEntityExt.getId();
                        paasFormDataEntity.setId(dataId);
                        // 执行业务规则
                        executionBusinessRule(formDataAddDTO, paasFormDataEntity);
                        packageSaasFormInsertSaveDTO(saasFormSaveDTO, paasFormDataEntity);
                        saasFormSaveDTO.setUseMap(excelImportExtraPoJo.getUserMap());
                        customerService.afterSaveForImport(saasFormSaveDTO);
                        saasNeedRedundantAttrPoJo = formDataAddDTO.getSaasNeedRedundantAttrPoJo();
                        List<ValidateDataDTO> needAddValidateDataDTO = null;
                        if (saasNeedRedundantAttrPoJo != null) {
                            needAddValidateDataDTO = saasNeedRedundantAttrPoJo.getNeedAddValidateDataDTO();
                        }
                        if (CollectionsUtil.isNotEmpty(needAddValidateDataDTO)) {
                            contactService.addBatchForImport(needAddValidateDataDTO, customerEntityExt, excelImportExtraPoJo.getUserMap(), formDataAddDTO);
                        }


                        // 客户导入如果没经纬度，对经纬度进行补充
                        Runnable runnable = () -> {
                            try {
                                JSONObject addressObj = customerEntityExt.getData().getJSONObject(CustomerManagementEnum.ADDRESS.getAttr());
                                if (Objects.nonNull(addressObj)) {
                                    String province = addressObj.getString(PaasConstant.PROVINCE);
                                    String city = addressObj.getString(PaasConstant.CITY);
                                    String district = addressObj.getString(PaasConstant.DISTRICT);
                                    String address = addressObj.getString(PaasConstant.ADDRESS);
                                    String addressStr = province + city + district + address;
                                    // 去除空格
                                    addressStr = addressStr.replaceAll(" +", "");
                                    if (StringUtil.isNotEmpty(addressStr)) {
                                        JSONObject location = addressObj.getJSONObject("location");
                                        if (Objects.nonNull(location)) {
                                            String lat = location.getString("lat");
                                            String lon = location.getString("lon");
                                            if (StringUtil.isEmpty(lat) || StringUtil.isEmpty(lon)) {
                                                JSONObject geo = GaodeGeoHelper.geo(addressStr, "");
                                                String latitude = geo.getString("latitude");
                                                String longitude = geo.getString("longitude");
                                                location.put("lat", latitude);
                                                location.put("lon", longitude);
                                                addressObj.put("location", location);
                                                JSONObject jsonObject = new JSONObject();
                                                jsonObject.put(CustomerManagementEnum.ADDRESS.getAttr(), addressObj);
                                                UpdateDataEntity updateData = ExplainUtil.getUpdateData(customerEntityExt.getId(), jsonObject, corpid);
                                                customerModel.updateBatch(Collections.singletonList(updateData), corpid, WriteRequest.RefreshPolicy.NONE);
                                            }
                                        } else {
                                            JSONObject geo = GaodeGeoHelper.geo(addressStr, "");
                                            if (Objects.nonNull(geo)) {
                                                String latitude = geo.getString("latitude");
                                                String longitude = geo.getString("longitude");
                                                location = new JSONObject();
                                                location.put("lat", latitude);
                                                location.put("lon", longitude);
                                                addressObj.put("location", location);
                                                JSONObject jsonObject = new JSONObject();
                                                jsonObject.put(CustomerManagementEnum.ADDRESS.getAttr(), addressObj);
                                                UpdateDataEntity updateData = ExplainUtil.getUpdateData(customerEntityExt.getId(), jsonObject, corpid);
                                                customerModel.updateBatch(Collections.singletonList(updateData), corpid, WriteRequest.RefreshPolicy.NONE);
                                            }
                                        }
                                    }
                                }
                            } catch (Exception e) {
                                LOG.error("customer import fixCustomerCoordinates error", e);
                            }
                        };
                        threadPoolBeanConfig.importCustomerCoordinatesRabbitMqThreadPool().execute(runnable);
                        try {
                            //评分更新(客户导入)
                            PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
                            BeanUtil.copyProperties(customerEntityExt,paasFormDataEntityExt);
                            scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CUSTOMER_MANAGEMENT,corpid,null,customerEntityExt);
                        } catch (Exception e) {
                            LOG.error("e{}",e.getMessage());
                        }
                        break;
                    default:
                        throw new XbbException(TemplateErrorCodeEnum.API_ERROR_350006);
                }
            }
        } catch (XbbException e) {
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            proEsHelper.physicalDeleteAllInAdd(dataId,corpid,businessType,saasMark);
            throw e;
        } catch (Exception e){
            LOG.error(BuinessDefaultErrorCodeEnum.API_ERROR_200018.getMsg(),e);
            proEsHelper.physicalDeleteAllInAdd(dataId,corpid,businessType,saasMark);
            throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200018);
        }
    }

    /**
     * 执行业务规则
     * @param formDataAddDTO
     * @param paasFormDataEntity
     */
    private void executionBusinessRule(FormDataAddDTO formDataAddDTO, PaasFormDataEntity paasFormDataEntity) {

        Runnable runnable = () -> {
            try {
                Long formId = paasFormDataEntity.getFormId();
                String corpid = formDataAddDTO.getCorpid();
                ActiveRuleDTO activeRuleDTO = new ActiveRuleDTO();
                BeanUtil.copyProperties(formDataAddDTO, activeRuleDTO);
                PaasFormEntity paasFormEntity = proFormHelp.getPaasForm(formId, activeRuleDTO.getBusinessType(), corpid);
                String businessRules = paasFormEntity.getBusinessRules();
                if (Objects.equals("1", businessRules)){
                    PaasFormExplainEntity paasFormExplainEntity = proFormHelp.getExplainEntity(corpid, formId, activeRuleDTO.getBusinessType());
                    activeRuleDTO.setDataId(paasFormDataEntity.getId());
                    PaasFormDataEntity newFormData = proModelService.getFormDataEntity(corpid, formDataAddDTO.getSaasMark(),formDataAddDTO.getBusinessType(), paasFormDataEntity.getId());

                    IndexTypeEnum indexTypeEnum = indexTypeModel.getSubIndexType(formDataAddDTO.getCorpid(), formDataAddDTO.getBusinessType(), formDataAddDTO.getSaasMark());
                    paasFormSubDataModel.transferSubForm(newFormData, indexTypeEnum);
                    activeRuleDTO.setPaasFormDataEntity(newFormData);
                    activeRuleDTO.setExplainList(JSON.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class));
                    formDataActiveRuleHelp.activeRule(activeRuleDTO);
                }
            }catch (XbbException e) {
                LOG.error("ExcelImportServiceImpl.executionBusinessRule失败", e);
            }
        };
        threadPoolBeanConfig.activeRuleThreadPool().execute(runnable);

    }
    /**
     * 避免代码冗余，提起数据封装
     *
     * @param saasFormSaveDTO    入参
     * @param paasFormDataEntity 数据实体
     * @date 2019/1/28 14:34
     */
    private void packageSaasFormInsertSaveDTO(SaasFormSaveDTO saasFormSaveDTO, PaasFormDataEntity paasFormDataEntity) {
        saasFormSaveDTO.setIsNew(true);
        saasFormSaveDTO.setOldData(paasFormDataEntity.getData());
        saasFormSaveDTO.setNewData(paasFormDataEntity.getData());
        saasFormSaveDTO.setNewPaasFormDataEntity(paasFormDataEntity);
        saasFormSaveDTO.setOldPaasFormDataEntity(paasFormDataEntity);
    }
}
